package com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ExceptionCast;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.CacheUtil;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.SmsAssetFixedStorage;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.SmsAssetProcess;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.SmsAssetProcessDetail;
import com.xyht.sca_s.student_manage_system.modules.asset.mapper.SmsAssetFixedStorageMapper;
import com.xyht.sca_s.student_manage_system.modules.asset.mapper.SmsAssetProcessDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.asset.mapper.SmsAssetProcessMapper;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.SmsAssetFixedDealApply;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.SmsAssetFixedDealApply;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.SmsAssetFixedDealGoods;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.SmsAssetFixedDealProcessDetail;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.Resp.SmsAssetFixedDealGoodsResp;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.Resp.SmsAssetFixedDealProcessDetailResp;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.SmsAssetFixedDealApply;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.SmsAssetFixedDealGoods;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.SmsAssetFixedDealProcessDetail;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.Resp.SmsAssetFixedDealApplyResp;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.Req.SmsAssetFixedDealGoodsReq;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.Req.SmsAssetFixedDealProcessDetailReq;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.mapper.SmsAssetFixedDealApplyMapper;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.mapper.SmsAssetFixedDealGoodsMapper;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.mapper.SmsAssetFixedDealProcessDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.Req.SmsAssetFixedDealApplyAllowReq;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.entity.Req.SmsAssetFixedDealApplyReq;
import com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.service.SmsAssetFixedDealApplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.AppTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.RangeTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.TipsTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.org.entity.SmsOrgStructure;
import com.xyht.sca_s.student_manage_system.modules.org.mapper.SmsOrgStructureMapper;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsRole;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.entity.resp.SmsSearchUserResp;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsRoleMapper;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.constant.CommonConstant.APPLY_MAX_SIZE;
import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetAllowStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetAllowStatusConstant.ASSET_ALLOW_STATUS_CANCEL;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetAllowTypeConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetBooleanConstant.ASSET_BOOLEAN_FALSE;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetBooleanConstant.ASSET_BOOLEAN_TRUE;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetObjectTypeConstant.ASSET_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetProcessTypeConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.AssetStatusConstant.ASSET_STATUS_OUT;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.CommonConstant.EXAMINE_STATUS_WAIT_ALLOW;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.ProcessObjectTypeConstant.PROCESS_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.constant.DealTypeConstant.DEAL_TYPE_OTHER;
import static com.xyht.sca_s.student_manage_system.modules.assetFixedDeal.constant.DealTypeConstant.DEAL_TYPE_SELL;

/**
 * <p>
 * 资产处置申请表 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2024-09-28
 */
@Service
public class SmsAssetFixedDealApplyServiceImpl extends ServiceImpl<SmsAssetFixedDealApplyMapper, SmsAssetFixedDealApply> implements SmsAssetFixedDealApplyService {
    @Resource
    private NewTipsUtil newTipsUtil;
    @Resource
    private SmsAssetFixedDealApplyMapper smsAssetFixedDealApplyMapper;
    @Resource
    private SmsAssetProcessMapper smsAssetProcessMapper;
    @Resource
    private SmsAssetProcessDetailMapper smsAssetProcessDetailMapper;
    @Resource
    private SmsAssetFixedStorageMapper smsAssetFixedStorageMapper;
    @Resource
    private SmsAssetFixedDealGoodsMapper smsAssetFixedDealGoodsMapper;
    @Resource
    private SmsAssetFixedDealProcessDetailMapper smsAssetFixedDealProcessDetailMapper;
    @Resource
    private SmsUserMapper smsUserMapper;
    @Resource
    private CacheUtil cacheUtil;
    @Resource
    private SmsOrgStructureMapper smsOrgStructureMapper;
    @Resource
    private SmsRoleMapper smsRoleMapper;


    @Override
    public ResponseResult addFixedDealApply(SmsAssetFixedDealApplyReq applyReq, String user_id) {
        if (applyReq.getGoodsList().size() < 1) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        for (SmsAssetFixedDealGoodsReq goodsReq : applyReq.getGoodsList()) {
            if (isNullOrEmpty(goodsReq.getAssetId(),goodsReq.getDealType())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }

            //校验资产是否属于当前申请人
            List<SmsAssetFixedStorage> fixedStorageList = smsAssetFixedStorageMapper.selectList(new QueryWrapper<SmsAssetFixedStorage>()
                    .lambda()
                    .eq(SmsAssetFixedStorage::getId, goodsReq.getAssetId())
                    .eq(SmsAssetFixedStorage::getAssetOwner, user_id));
            if (fixedStorageList == null || fixedStorageList.size() < 1){
                return CommonResult.failed(CommonCodeEnum.ASSET_APPLY_NOT_EXIST);
            }

            //校验申请类型
            if (goodsReq.getDealType() < DEAL_TYPE_SELL ||  goodsReq.getDealType() > DEAL_TYPE_OTHER){
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
        }

        Integer applyCount = smsAssetFixedDealApplyMapper.selectCount(new QueryWrapper<SmsAssetFixedDealApply>()
                .lambda()
                .eq(SmsAssetFixedDealApply::getApplyUserId, user_id)
                .eq(SmsAssetFixedDealApply::getAllowStatus, ASSET_ALLOW_STATUS_WAIT_ALLOW));
        if (applyCount >= APPLY_MAX_SIZE) {
            return CommonResult.failed(CommonCodeEnum.ASSET_APPLY_MAX_LIMIT);
        }

        SmsAssetProcess originProcess = smsAssetProcessMapper.selectOne(new QueryWrapper<SmsAssetProcess>()
                .lambda()
                .eq(SmsAssetProcess::getProcessType, ASSET_PROCESS_TYPE_FIXED_DEAL));
        if (originProcess == null) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_PROCESS_NOT_SETTING));
        }

        List<SmsAssetProcessDetail> fillProcessList =
                smsAssetProcessDetailMapper.selectList(new QueryWrapper<SmsAssetProcessDetail>()
                        .lambda()
                        .eq(SmsAssetProcessDetail::getProcessDetailIsApplicantEdit, true)
                        .eq(SmsAssetProcessDetail::getProcessDetailIsUse, true)
                        .eq(SmsAssetProcessDetail::getProcessId, originProcess.getId())
                        .orderByAsc(SmsAssetProcessDetail::getProcessDetailSort));
        if (fillProcessList != null && fillProcessList.size() > 0) {
            if (applyReq.getProcessList() == null || applyReq.getProcessList().size() < 1) {
                return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_USER_NOT_SETTING);
            }
            //判断申请人是否将全部需要编辑流程填写
            List<SmsAssetProcessDetail> filterList = fillProcessList
                    .stream()
                    .filter(process -> {
                                List<SmsAssetFixedDealProcessDetailReq> result = applyReq.getProcessList()
                                        .stream()
                                        .filter(fillProcess -> fillProcess.getProcessDetailId().equals(process.getId()))
                                        .collect(Collectors.toList());
                                //匹配的去除  未匹配的留下
                                return result.size() == 0;
                            }
                    )
                    .collect(Collectors.toList());
            if (filterList.size() > 0) {
                return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_PROCESS_NOT_FILL);
            }
        }

        //创建申请表
        SmsAssetFixedDealApply smsAssetFixedDealApply = new SmsAssetFixedDealApply();
        BeanUtils.copyProperties(applyReq, smsAssetFixedDealApply);
        smsAssetFixedDealApply.setApplyUserId(user_id);
        smsAssetFixedDealApply.setAllowStatus(ASSET_ALLOW_STATUS_WAIT_ALLOW);
        smsAssetFixedDealApplyMapper.insert(smsAssetFixedDealApply);

        if (smsAssetFixedDealApply.getId() == null) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        String apply_id = smsAssetFixedDealApply.getId();

        //创建入库申请物品记录
        for (SmsAssetFixedDealGoodsReq goodsReq : applyReq.getGoodsList()) {

            SmsAssetFixedDealGoods addAssetApplyGoods = new SmsAssetFixedDealGoods();
            BeanUtils.copyProperties(goodsReq, addAssetApplyGoods);
            addAssetApplyGoods.setApplyId(apply_id);
            smsAssetFixedDealGoodsMapper.insert(addAssetApplyGoods);
        }

        //创建审批流程
        //主流程

        //流程节点
        List<SmsAssetProcessDetail> originProcessDetailList =
                smsAssetProcessDetailMapper.selectList(new QueryWrapper<SmsAssetProcessDetail>()
                        .lambda()
                        .eq(SmsAssetProcessDetail::getProcessDetailIsUse, ASSET_BOOLEAN_TRUE)
                        .eq(SmsAssetProcessDetail::getProcessId, originProcess.getId())
                        .orderByAsc(SmsAssetProcessDetail::getProcessDetailSort));
        if (originProcessDetailList == null || originProcessDetailList.size() < 1) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ASSET_PROCESS_NOT_SETTING));
        }
        int sort = 1;
        for (SmsAssetProcessDetail process : originProcessDetailList) {
            //判断管理员是否配置初始流程
            if (process.getProcessDetailIsApplicantEdit().equals(ASSET_BOOLEAN_FALSE)) {
                if (isNullOrEmpty(process.getProcessDetailObjectId()) || isNullOrEmpty(process.getProcessDetailObjectType())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.PAYMENT_PROCESS_NOT_SETTING));
                }
            }

            SmsAssetFixedDealProcessDetail addDetail =
                    new SmsAssetFixedDealProcessDetail();

            addDetail.setApplyId(apply_id);
            addDetail.setProcessDetailId(process.getId());
            addDetail.setProcessDetailIsSign(process.getProcessDetailIsSign());
            addDetail.setProcessDetailIsStamp(process.getProcessDetailIsStamp());
            addDetail.setProcessDetailName(process.getProcessDetailName());
            addDetail.setProcessDetailStatus(ASSET_ALLOW_STATUS_WAIT_ALLOW);

            addDetail.setProcessDetailSort(sort++);

            //申请人可编辑流程
            if (process.getProcessDetailIsApplicantEdit().equals(ASSET_BOOLEAN_TRUE)) {
                List<SmsAssetFixedDealProcessDetailReq> filterList = applyReq.getProcessList()
                        .stream()
                        .filter(fillProcess -> fillProcess.getProcessDetailId().equals(process.getId()))
                        .collect(Collectors.toList());
                if (filterList.size() < 1) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.PAYMENT_ALLOW_PROCESS_NOT_FILL));
                }
                SmsAssetFixedDealProcessDetailReq fillProcessReq = filterList.get(0);

                if (isNullOrEmpty(fillProcessReq.getProcessDetailObjectId())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
                }
                addDetail.setProcessDetailObjectId(fillProcessReq.getProcessDetailObjectId());
                addDetail.setProcessDetailObjectType(ASSET_OBJECT_TYPE_PERSON);
            } else {
                addDetail.setProcessDetailObjectId(process.getProcessDetailObjectId());
                addDetail.setProcessDetailObjectType(process.getProcessDetailObjectType());
            }
            smsAssetFixedDealProcessDetailMapper.insert(addDetail);
        }

        //消息通知
        //通知流程第一个节点
        SmsAssetFixedDealProcessDetail firstDetail =
                smsAssetFixedDealProcessDetailMapper.selectOne(new QueryWrapper<SmsAssetFixedDealProcessDetail>()
                        .lambda()
                        .eq(SmsAssetFixedDealProcessDetail::getApplyId, apply_id)
                        .eq(SmsAssetFixedDealProcessDetail::getProcessDetailSort, 1)
                        .orderByAsc(SmsAssetFixedDealProcessDetail::getProcessDetailSort));
        RangeTypeEnum rangeTypeEnum;
        if (firstDetail.getProcessDetailIsApplicantEdit() == ASSET_BOOLEAN_TRUE) {
            rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
        } else {
            if (firstDetail.getProcessDetailObjectType() == ASSET_OBJECT_TYPE_PERSON) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
        }

        List<String> rangeList = new ArrayList<>();
        rangeList.add(firstDetail.getProcessDetailObjectId());

        newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW,
                user_id,
                rangeTypeEnum,
                rangeList,
                AppTypeEnum.APP_TYPE_ENUM_ASSET_MANAGEMENT,
                apply_id,
                firstDetail.getId());
        return CommonResult.success();
    }

    @Override
    public ResponseResult cancelFixedDealApply(SmsAssetFixedDealApplyReq applyReq, String user_id) {
        if (isNullOrEmpty(applyReq.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsAssetFixedDealApply assetApply = smsAssetFixedDealApplyMapper.selectOne(new QueryWrapper<SmsAssetFixedDealApply>()
                .lambda()
                .eq(SmsAssetFixedDealApply::getApplyUserId, user_id)
                .eq(SmsAssetFixedDealApply::getId, applyReq.getId()));
        if (assetApply == null) {
            return CommonResult.failed(CommonCodeEnum.ASSET_APPLY_NOT_EXIST);
        }

        if (assetApply.getAllowStatus() != EXAMINE_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.PAYMENT_CANCEL_FAIL_ALLOWED);
        }

        //判断是否审批中
        List<SmsAssetFixedDealProcessDetail> detailList =
                smsAssetFixedDealProcessDetailMapper.selectList(new QueryWrapper<SmsAssetFixedDealProcessDetail>()
                        .lambda()
                        .eq(SmsAssetFixedDealProcessDetail::getApplyId, applyReq.getId())
                        .eq(SmsAssetFixedDealProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_PASS));
        if (detailList != null && detailList.size() > 0) {
            return CommonResult.failed(CommonCodeEnum.ASSET_CANCEL_FAIL_ALLOWING);
        }

        //撤回审批
        SmsAssetFixedDealApply cancelApply = new SmsAssetFixedDealApply();
        cancelApply.setId(applyReq.getId());
        cancelApply.setAllowStatus(ASSET_ALLOW_STATUS_CANCEL);
        cancelApply.setEndTime(new Date());
        smsAssetFixedDealApplyMapper.updateById(cancelApply);

        //修改节点状态
        SmsAssetFixedDealProcessDetail cancelProcessDetail = new SmsAssetFixedDealProcessDetail();
        cancelProcessDetail.setProcessDetailStatus(ASSET_ALLOW_STATUS_CANCEL);

        smsAssetFixedDealProcessDetailMapper.update(cancelProcessDetail, new QueryWrapper<SmsAssetFixedDealProcessDetail>()
                .lambda()
                .eq(SmsAssetFixedDealProcessDetail::getApplyId, applyReq.getId()));

        //消息通知
        newTipsUtil.cancelFinishTips(applyReq.getId());
        return CommonResult.success();
    }

    @Override
    public ResponseResult getAssetFixedDealApplyList(String user_id, Integer apply_type, Integer pageNum, Integer pageSize) {
        if (isNullOrEmpty(apply_type)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<SmsAssetFixedDealApplyResp> respList = new ArrayList<>();
        int total = 0;
        if (apply_type == ASSET_ALLOW_TYPE_APPLY) {
            Page<SmsAssetFixedDealApply> page = new Page<>(pageNum, pageSize);
            QueryWrapper<SmsAssetFixedDealApply> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(SmsAssetFixedDealApply::getApplyUserId, user_id)
                    .orderByDesc(SmsAssetFixedDealApply::getCreateTime);
            smsAssetFixedDealApplyMapper.selectPage(page, queryWrapper);
            respList = page.getRecords()
                    .stream()
                    .map(apply -> {
                        SmsAssetFixedDealApplyResp storageApplyResp =
                                new SmsAssetFixedDealApplyResp();
                        BeanUtils.copyProperties(apply, storageApplyResp);
                        storageApplyResp.setId(apply.getId());

                        SmsUser smsUser = smsUserMapper.selectById(apply.getApplyUserId());
                        SmsSearchUserResp userResp = new SmsSearchUserResp();
                        if (smsUser != null) {
                            BeanUtils.copyProperties(smsUser, userResp);
                        }
                        storageApplyResp.setApplyUserInfo(userResp);

                        return storageApplyResp;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        } else if (apply_type == ASSET_ALLOW_TYPE_ALLOWED) {
            //获取已审批的申请
            Page<SmsAssetFixedDealProcessDetail> page = new Page<>(pageNum, pageSize);
            LambdaQueryWrapper<SmsAssetFixedDealProcessDetail> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SmsAssetFixedDealProcessDetail::getAllowUserId, user_id)
                    .orderByDesc(SmsAssetFixedDealProcessDetail::getEndTime);
            smsAssetFixedDealProcessDetailMapper.selectPage(page, queryWrapper);

            respList = page.getRecords()
                    .stream()
                    .map(smsMPJResp -> {
                        SmsAssetFixedDealApplyResp applyResp = new SmsAssetFixedDealApplyResp();
                        applyResp.setAllowUserId(smsMPJResp.getAllowUserId());

                        //获取申请信息
                        SmsAssetFixedDealApply apply = smsAssetFixedDealApplyMapper.selectById(smsMPJResp.getApplyId());
                        BeanUtils.copyProperties(apply, applyResp);

                        SmsUser applyUser = cacheUtil.getUserInfo(applyResp.getApplyUserId());
                        SmsSearchUserResp applyUserResp = new SmsSearchUserResp();
                        if (applyUser != null) {
                            BeanUtils.copyProperties(applyUser, applyUserResp);
                        }
                        applyResp.setApplyUserInfo(applyUserResp);

                        SmsUser allowUser = cacheUtil.getUserInfo(applyResp.getAllowUserId());
                        SmsSearchUserResp allowUserResp = new SmsSearchUserResp();
                        if (allowUser != null) {
                            BeanUtils.copyProperties(allowUser, allowUserResp);
                        }
                        applyResp.setAllowUserInfo(allowUserResp);

                        applyResp.setDetailId(smsMPJResp.getId());
                        applyResp.setProcessDetailStatus(smsMPJResp.getProcessDetailStatus());

                        return applyResp;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        } else if (apply_type == ASSET_ALLOW_TYPE_WAIT_ALLOW) {
            List<String> roleList = cacheUtil.getRoleList(user_id);

            //获取所有待审批申请流程节点
            List<SmsAssetFixedDealProcessDetail> allDetailList =
                    smsAssetFixedDealProcessDetailMapper.selectList(new QueryWrapper<SmsAssetFixedDealProcessDetail>()
                            .lambda()
                            .eq(SmsAssetFixedDealProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_WAIT_ALLOW));

            List<SmsAssetFixedDealProcessDetail> filterDetailList = allDetailList.stream()
                    .filter(detail -> {
                        if (detail.getProcessDetailIsApplicantEdit() == ASSET_BOOLEAN_TRUE) {
                            if (!detail.getProcessDetailObjectId().equals(user_id)) {
                                return false;
                            }
                        } else {
                            if (detail.getProcessDetailObjectType() == ASSET_OBJECT_TYPE_PERSON) {
                                if (!detail.getProcessDetailObjectId().equals(user_id)) {
                                    return false;
                                }
                            } else {
                                List<String> filterRoleList = roleList.stream().filter(role -> role.equals(detail.getProcessDetailObjectId())).collect(Collectors.toList());
                                if (filterRoleList.size() < 1) {
                                    return false;
                                }
                            }
                        }

                        if (detail.getProcessDetailSort().equals(1)) {
                            return true;
                        }
                        //判断上一个流程节点是否完成
                        SmsAssetFixedDealProcessDetail preDetail =
                                smsAssetFixedDealProcessDetailMapper.selectOne(new QueryWrapper<SmsAssetFixedDealProcessDetail>()
                                        .lambda()
                                        .eq(SmsAssetFixedDealProcessDetail::getApplyId, detail.getApplyId())
                                        .eq(SmsAssetFixedDealProcessDetail::getProcessDetailSort, detail.getProcessDetailSort() - 1)
                                        .eq(SmsAssetFixedDealProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_PASS));
                        if (preDetail == null || isNullOrEmpty(preDetail.getId())) {
                            return false;
                        }
                        return true;
                    })
                    .collect(Collectors.toList());
            if (filterDetailList.size() > 0) {
                respList = filterDetailList
                        .stream()
                        .map(processDetail -> {
                            SmsAssetFixedDealApplyResp applyResp = new SmsAssetFixedDealApplyResp();

                            //获取申请信息
                            SmsAssetFixedDealApply apply = smsAssetFixedDealApplyMapper.selectById(processDetail.getApplyId());
                            BeanUtils.copyProperties(apply, applyResp);

                            SmsUser applyUser = cacheUtil.getUserInfo(applyResp.getApplyUserId());
                            SmsSearchUserResp applyUserResp = new SmsSearchUserResp();
                            if (applyUser != null) {
                                BeanUtils.copyProperties(applyUser, applyUserResp);
                            }
                            applyResp.setApplyUserInfo(applyUserResp);

                            applyResp.setDetailId(processDetail.getId());
                            applyResp.setProcessDetailStatus(processDetail.getProcessDetailStatus());

                            return applyResp;
                        })
                        .skip((pageNum - 1) * pageSize) // 跳过起始索引之前的部分
                        .limit(pageSize)  // 限制返回的元素数量
                        .collect(Collectors.toList());
                total = filterDetailList.size();

            }
        }
        return CommonResult.success(respList, total);
    }

    @Override
    public ResponseResult getAssetFixedDealApplyDetail(String apply_id, String user_id) {
        if (isNullOrEmpty(apply_id)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsAssetFixedDealApply assetApply = smsAssetFixedDealApplyMapper.selectById(apply_id);
        if (assetApply == null || isNullOrEmpty(assetApply.getId())) {
            return CommonResult.failed(CommonCodeEnum.ASSET_APPLY_NOT_EXIST);
        }

        SmsAssetFixedDealApplyResp applyResp = new SmsAssetFixedDealApplyResp();
        BeanUtils.copyProperties(assetApply, applyResp);

        SmsUser smsUser = cacheUtil.getUserInfo(applyResp.getApplyUserId());
        SmsSearchUserResp smsUserResp = new SmsSearchUserResp();
        if (smsUser != null) {
            BeanUtils.copyProperties(smsUser, smsUserResp);
        }
        applyResp.setApplyUserInfo(smsUserResp);

        //封装流程节点
        List<SmsAssetFixedDealProcessDetailResp> detailRespList =
                smsAssetFixedDealProcessDetailMapper.selectList(new QueryWrapper<SmsAssetFixedDealProcessDetail>()
                                .lambda()
                                .eq(SmsAssetFixedDealProcessDetail::getApplyId, apply_id)
                                .orderByAsc(SmsAssetFixedDealProcessDetail::getProcessDetailSort))
                        .stream()
                        .map(detail -> {
                            SmsAssetFixedDealProcessDetailResp detailResp = new SmsAssetFixedDealProcessDetailResp();
                            BeanUtils.copyProperties(detail, detailResp);

                            if (!isNullOrEmpty(detailResp.getAllowUserId())) {
                                SmsUser userInfo = cacheUtil.getUserInfo(detailResp.getAllowUserId());
                                SmsSearchUserResp smsSearchUserResp = new SmsSearchUserResp();
                                if (userInfo != null) {
                                    BeanUtils.copyProperties(userInfo, smsSearchUserResp);
                                }
                                detailResp.setAllowUserInfo(smsSearchUserResp);
                            }

                            if(detail.getProcessDetailObjectType() == PROCESS_OBJECT_TYPE_PERSON){
                                SmsUser allowUser = cacheUtil.getUserInfo(detail.getProcessDetailObjectId());
                                if(allowUser != null) {
                                    detailResp.setObjectName(allowUser.getRealName());
                                    detailResp.setObjectPic(allowUser.getUserPic());
                                }
                            }else {
                                SmsRole smsRole = smsRoleMapper.selectById(detail.getProcessDetailObjectId());
                                if(smsRole != null) {
                                    detailResp.setObjectName(smsRole.getRoleName());
                                }
                            }
                            return detailResp;
                        })
                        .collect(Collectors.toList());
        applyResp.setProcessList(detailRespList);

        //封装物品信息
        List<SmsAssetFixedDealGoodsResp> goodsList =
                smsAssetFixedDealGoodsMapper.selectList(new QueryWrapper<SmsAssetFixedDealGoods>()
                                .lambda()
                                .eq(SmsAssetFixedDealGoods::getApplyId, apply_id))
                        .stream()
                        .map(goods -> {
                            SmsAssetFixedDealGoodsResp goodsResp = new SmsAssetFixedDealGoodsResp();
                            BeanUtils.copyProperties(goods, goodsResp);

                            return goodsResp;
                        })
                        .collect(Collectors.toList());
        applyResp.setGoodsList(goodsList);
        return CommonResult.success(applyResp);
    }

    @Override
    public ResponseResult allowAssetFixedDealApply(SmsAssetFixedDealApplyAllowReq smsAssetFixedDealApplyAllowReq, String user_id) {
        if (isNullOrEmpty(smsAssetFixedDealApplyAllowReq.getApplyId()) || isNullOrEmpty(smsAssetFixedDealApplyAllowReq.getDetailId())
                || isNullOrEmpty(smsAssetFixedDealApplyAllowReq.getProcessDetailStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (smsAssetFixedDealApplyAllowReq.getProcessDetailStatus() != ASSET_ALLOW_STATUS_PASS
                && smsAssetFixedDealApplyAllowReq.getProcessDetailStatus() != ASSET_ALLOW_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsAssetFixedDealApply inStorageApply = smsAssetFixedDealApplyMapper.selectById(smsAssetFixedDealApplyAllowReq.getApplyId());
        if (inStorageApply == null || isNullOrEmpty(inStorageApply.getId())) {
            return CommonResult.failed(CommonCodeEnum.ASSET_APPLY_NOT_EXIST);
        }

        SmsAssetFixedDealProcessDetail processDetail =
                smsAssetFixedDealProcessDetailMapper.selectOne(new QueryWrapper<SmsAssetFixedDealProcessDetail>()
                        .lambda()
                        .eq(SmsAssetFixedDealProcessDetail::getApplyId, smsAssetFixedDealApplyAllowReq.getApplyId())
                        .eq(SmsAssetFixedDealProcessDetail::getId, smsAssetFixedDealApplyAllowReq.getDetailId())
                        .eq(SmsAssetFixedDealProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_WAIT_ALLOW));
        if (processDetail == null || isNullOrEmpty(processDetail.getId())) {
            return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_FAIL);
        }

        //判断该节点是否本人审批（防止跳节点审批）
        if (processDetail.getProcessDetailObjectType() == ASSET_OBJECT_TYPE_PERSON) {
            if (!processDetail.getProcessDetailObjectId().equals(user_id)) {
                return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_FAIL);
            }
        } else {
            List<String> roleList = cacheUtil.getRoleList(user_id);
            List<String> filterRoleList = roleList.stream().filter(role -> role.equals(processDetail.getProcessDetailObjectId())).collect(Collectors.toList());
            if (filterRoleList.size() < 1) {
                return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_FAIL);
            }
        }

        if (!processDetail.getProcessDetailSort().equals(1)) {
            SmsAssetFixedDealProcessDetail preDetail =
                    smsAssetFixedDealProcessDetailMapper.selectOne(new QueryWrapper<SmsAssetFixedDealProcessDetail>()
                            .lambda()
                            .eq(SmsAssetFixedDealProcessDetail::getApplyId, smsAssetFixedDealApplyAllowReq.getApplyId())
                            .eq(SmsAssetFixedDealProcessDetail::getProcessDetailSort, processDetail.getProcessDetailSort() - 1));
            if (preDetail != null && isNullOrEmpty(preDetail.getId())) {
                if (preDetail.getProcessDetailStatus() != ASSET_ALLOW_STATUS_PASS) {
                    return CommonResult.failed(CommonCodeEnum.ASSET_ALLOW_FAIL);
                }
            }
        }

        SmsAssetFixedDealProcessDetail allowDetail = new SmsAssetFixedDealProcessDetail();
        allowDetail.setId(smsAssetFixedDealApplyAllowReq.getDetailId());
        allowDetail.setProcessDetailStatus(smsAssetFixedDealApplyAllowReq.getProcessDetailStatus());
        if (!isNullOrEmpty(smsAssetFixedDealApplyAllowReq.getProcessDetailRemark())) {
            allowDetail.setProcessDetailRemark(smsAssetFixedDealApplyAllowReq.getProcessDetailRemark());
        }
        Date nowDate = new Date();
        allowDetail.setEndTime(nowDate);
        allowDetail.setAllowUserId(user_id);

        if (processDetail.getProcessDetailIsSign() == ASSET_BOOLEAN_TRUE) {
            if (isNullOrEmpty(smsAssetFixedDealApplyAllowReq.getProcessDetailSign())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            allowDetail.setProcessDetailSign(smsAssetFixedDealApplyAllowReq.getProcessDetailSign());
        }
        if (processDetail.getProcessDetailIsStamp() == ASSET_BOOLEAN_TRUE) {
            if (isNullOrEmpty(smsAssetFixedDealApplyAllowReq.getProcessDetailStamp())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            allowDetail.setProcessDetailStamp(smsAssetFixedDealApplyAllowReq.getProcessDetailStamp());
        }
        smsAssetFixedDealProcessDetailMapper.updateById(allowDetail);

        boolean is_done = false;

        //判断是否最后一个节点 是否驳回
        Integer detailCount = smsAssetFixedDealProcessDetailMapper.selectCount(new QueryWrapper<SmsAssetFixedDealProcessDetail>()
                .lambda()
                .eq(SmsAssetFixedDealProcessDetail::getApplyId, smsAssetFixedDealApplyAllowReq.getApplyId()));
        if (detailCount.equals(processDetail.getProcessDetailSort()) || smsAssetFixedDealApplyAllowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_DENY) {
            is_done = true;

            SmsAssetFixedDealApply updateApply = new SmsAssetFixedDealApply();
            updateApply.setId(smsAssetFixedDealApplyAllowReq.getApplyId());
            updateApply.setEndTime(nowDate);
            updateApply.setAllowStatus(smsAssetFixedDealApplyAllowReq.getProcessDetailStatus());
            smsAssetFixedDealApplyMapper.updateById(updateApply);
        }

        //流程结束且同意，
        if (detailCount.equals(processDetail.getProcessDetailSort()) && smsAssetFixedDealApplyAllowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_PASS) {
            List<SmsAssetFixedDealGoods> list = smsAssetFixedDealGoodsMapper.selectList(new QueryWrapper<SmsAssetFixedDealGoods>()
                    .lambda()
                    .eq(SmsAssetFixedDealGoods::getApplyId, smsAssetFixedDealApplyAllowReq.getApplyId()));
            if (list!= null && list.size() > 0){
                for (SmsAssetFixedDealGoods goods : list) {
                    SmsAssetFixedStorage updateStorage = new SmsAssetFixedStorage();
                    updateStorage.setId(goods.getAssetId());

                    updateStorage.setAssetStatus(ASSET_STATUS_OUT);
                    Integer assetDetailStatus = generateDetailStatus(ASSET_STATUS_OUT,goods.getDealType());
                    updateStorage.setAssetDetailStatus(assetDetailStatus);

                    smsAssetFixedStorageMapper.updateById(updateStorage);
                }
            }

            //修改申请状态
            SmsAssetFixedDealApply updateApply = new SmsAssetFixedDealApply();
            updateApply.setId(smsAssetFixedDealApplyAllowReq.getApplyId());
            updateApply.setEndTime(nowDate);
            updateApply.setAllowStatus(ASSET_ALLOW_STATUS_PASS);
            smsAssetFixedDealApplyMapper.updateById(updateApply);
        }

        //节点驳回 重置其余节点状态
        if (smsAssetFixedDealApplyAllowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_DENY) {
            SmsAssetFixedDealProcessDetail updateDenyDetail =
                    new SmsAssetFixedDealProcessDetail();
            updateDenyDetail.setProcessDetailStatus(ASSET_ALLOW_STATUS_DENY_FINISH);
            smsAssetFixedDealProcessDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsAssetFixedDealProcessDetail>()
                    .lambda()
                    .eq(SmsAssetFixedDealProcessDetail::getApplyId, smsAssetFixedDealApplyAllowReq.getApplyId())
                    .eq(SmsAssetFixedDealProcessDetail::getProcessDetailStatus, ASSET_ALLOW_STATUS_WAIT_ALLOW));
        }

        //消息通知
        if (is_done) {
            boolean result_status = false;
            if (smsAssetFixedDealApplyAllowReq.getProcessDetailStatus() == ASSET_ALLOW_STATUS_PASS) {
                result_status = true;
            }
            newTipsUtil.allowFinishTips(smsAssetFixedDealApplyAllowReq.getApplyId(), user_id, result_status);
        } else {
            SmsAssetFixedDealProcessDetail nextDetail =
                    smsAssetFixedDealProcessDetailMapper.selectOne(new QueryWrapper<SmsAssetFixedDealProcessDetail>()
                            .lambda()
                            .eq(SmsAssetFixedDealProcessDetail::getApplyId, smsAssetFixedDealApplyAllowReq.getApplyId())
                            .eq(SmsAssetFixedDealProcessDetail::getProcessDetailSort, processDetail.getProcessDetailSort() + 1));
            RangeTypeEnum rangeTypeEnum;
            if (nextDetail.getProcessDetailIsApplicantEdit() == ASSET_BOOLEAN_TRUE) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                if (nextDetail.getProcessDetailObjectType() == ASSET_OBJECT_TYPE_PERSON) {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
                } else {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
                }
            }

            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessDetailObjectId());
            newTipsUtil.allowContinueTips(smsAssetFixedDealApplyAllowReq.getApplyId(),
                    user_id,
                    rangeTypeEnum,
                    rangeIDList,
                    nextDetail.getId());
        }
        return CommonResult.success();
    }

    private Integer generateDetailStatus(Integer head, Integer tail){
        if (head == null || tail == null) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        // 拼接逻辑
        if (tail < 10) {
            // tail 小于 10，中间插入 0
            return Integer.parseInt(head.toString() + "0" + tail.toString());
        } else {
            // tail 大于等于 10，直接拼接
            return Integer.parseInt(head.toString() + tail.toString());
        }
    }

    @Override
    public ResponseResult getAssetFixedDealApplyAllList(Integer allowStatus, String applyUserName, Integer pageNum, Integer pageSize) {
        Page<SmsAssetFixedDealApply> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<SmsAssetFixedDealApply> fixedInStorageApplyLambdaQueryWrapper = new LambdaQueryWrapper<SmsAssetFixedDealApply>()
                .orderByDesc(SmsAssetFixedDealApply::getCreateTime);
        if (!isNullOrEmpty(allowStatus)) {
            fixedInStorageApplyLambdaQueryWrapper.eq(SmsAssetFixedDealApply::getAllowStatus,allowStatus);
        }

        //模糊查询申请人
        List<String> smsUserList = new ArrayList<>();
        if (!isNullOrEmpty(applyUserName)){
            smsUserList = smsUserMapper.selectList(new LambdaQueryWrapper<SmsUser>()
                            .like(SmsUser::getRealName, applyUserName))
                    .stream()
                    .map(SmsUser::getId)
                    .collect(Collectors.toList());
        }

        if (smsUserList.size() > 0){
            fixedInStorageApplyLambdaQueryWrapper.in(SmsAssetFixedDealApply::getApplyUserId,smsUserList);
        }

        smsAssetFixedDealApplyMapper.selectPage(page,fixedInStorageApplyLambdaQueryWrapper);
        List<SmsAssetFixedDealApplyResp> respList = page.getRecords()
                .stream()
                .map(SmsAssetFixedDealApply -> {
                    SmsAssetFixedDealApplyResp applyResp = new SmsAssetFixedDealApplyResp();
                    BeanUtils.copyProperties(SmsAssetFixedDealApply, applyResp);

                    SmsUser smsUser = cacheUtil.getUserInfo(applyResp.getApplyUserId());
                    SmsSearchUserResp smsUserResp = new SmsSearchUserResp();
                    if (smsUser != null) {
                        BeanUtils.copyProperties(smsUser, smsUserResp);
                    }
                    applyResp.setApplyUserInfo(smsUserResp);

                    return applyResp;
                })
                .collect(Collectors.toList());
        return CommonResult.success(respList,(int)page.getTotal());
    }
}
